package com.foreveredu.erlms.web.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipCompress {
    private String basePath;  
    private String zipPath;  
      
    /** 
     *  
     * @param basePath:the base path.eg:windows 'D:\\iknow\\', linux 'D:/iknow/' 
     * @param zipPath:the compressed zip file's name and path.eg:'D:\\iknow.zip' 
     */  
    public ZipCompress(String basePath,String zipPath){  
        this.basePath = trimSlash(basePath);  
        this.zipPath = trimSlash(zipPath);  
    }  
      
    /** 
     * if the path 's last character is '/' or '\' then trim it. 
     * @param path 
     * @return 
     */  
    private String trimSlash(String path){  
        if(path == null || "".equals(path)){  
            return "";  
        }  
        path = path.replace("/", File.separator);  
        if(path.endsWith(File.separator)){  
            path = path.substring(0 , path.length() -1);  
        }  
        return path;  
    }  
      
    /** 
     * the method provide for foreign transfer. 
     */  
    public void compress(){  
        ZipOutputStream zipOut = null;  
        try{    
            FileOutputStream fileOut = new FileOutputStream(this.zipPath);    
            CheckedOutputStream checkOut = new CheckedOutputStream(fileOut,new CRC32());    
            zipOut = new ZipOutputStream(new BufferedOutputStream(checkOut));   
            zipOut.setComment("this is a iknow exported zip file.");    
            cycleFile(zipOut,this.basePath,"");  
        }catch(IOException e){    
            e.printStackTrace();  
        }finally{  
            if(zipOut != null){  
                try {  
                    zipOut.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
      
    /** 
     * repeatedly transfer the method to visit all of the files listed on the basepath. 
     * @param zipOut 
     * @param filePath 
     * @param relativePath 
     */  
    private void cycleFile(ZipOutputStream zipOut,String filePath,String relativePath){  
        File file = new File(filePath);  
        if(file.isFile()){  
            write(zipOut,filePath,relativePath);  
        }else{  
            File[] children = file.listFiles();  
            for(File f : children){  
                String tmpFilePath = filePath + File.separator + f.getName();  
                String tmpRelativePath = null;  
                if("".equals(relativePath)){  
                    tmpRelativePath = f.getName();  
                }else{  
                    tmpRelativePath = relativePath + File.separator + f.getName();  
                }  
                cycleFile(zipOut,tmpFilePath,tmpRelativePath);  
            }  
        }  
    }  
      
    private void write(ZipOutputStream zipOut,String filePath,String fileName){  
        FileInputStream fis = null;  
        try {  
            zipOut.putNextEntry(new ZipEntry(fileName));  
            fis = new FileInputStream(filePath);  
            int size = 1024;  
            int length = fis.available();  
            int len = (length % size == 0) ? length/size : length/size + 1;  
            byte[] temp = new byte[size];  
            for( int i = 0 ; i < len ; i++ ){  
                length = fis.read(temp);  
                zipOut.write(temp,0,length);  
            }  
        }catch (Exception e) {  
            e.printStackTrace();  
        }finally{  
            if(fis != null){  
                try {  
                    fis.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }    
            }  
        }  
    } 
    
//    public static void main(String[] args) {
//    	ZipCompress zcCompress = new ZipCompress("d:/images", "d:/images.zip");
//    	zcCompress.compress();
//    }
}
